Prepare data
Read and format data
Prevalence
df_uk_prev <- read_csv('UK_timeseries_prep_2005.csv')
Parsed with column specification:
cols(
ut_area = [31mcol_character()[39m,
date = [31mcol_character()[39m,
cumcase = [32mcol_double()[39m,
poptotal = [32mcol_double()[39m,
rate = [32mcol_double()[39m
)
df_uk_prev <- df_uk_prev %>%
select(ut_area, date, rate) %>%
rename(rate_day = rate) %>%
mutate(date = as.Date(date, "%d%b%Y"))
df_uk_prev
Personality
df_uk_pers <- read_csv('timeseries_uk_utla_march9_april_09.csv')
Parsed with column specification:
cols(
ut_area = [31mcol_character()[39m,
time = [32mcol_double()[39m,
areaname = [31mcol_character()[39m,
open = [32mcol_double()[39m,
extra = [32mcol_double()[39m,
agree = [32mcol_double()[39m,
neuro = [32mcol_double()[39m,
sci = [32mcol_double()[39m,
frequ = [32mcol_double()[39m,
ut_name = [31mcol_character()[39m,
poptotal = [32mcol_double()[39m,
rate_day = [32mcol_double()[39m
)
df_uk_pers <- df_uk_pers %>%
select(ut_area, open, agree, neuro, sci, extra) %>%
dplyr::rename(pers_o = open,
pers_c = sci,
pers_e = extra,
pers_a = agree,
pers_n = neuro) %>%
distinct()
df_uk_pers
NA
Social distancing
df_uk_socdist <- read_csv('UK_socdist_fb_nuts3.csv')
Parsed with column specification:
cols(
nuts3 = [31mcol_character()[39m,
date = [34mcol_date(format = "")[39m,
all_day_bing_tiles_visited_relat = [32mcol_double()[39m,
all_day_ratio_single_tile_users = [32mcol_double()[39m,
open = [32mcol_double()[39m,
extra = [32mcol_double()[39m,
agree = [32mcol_double()[39m,
neuro = [32mcol_double()[39m,
sci = [32mcol_double()[39m,
frequ = [32mcol_double()[39m,
nuts3_name = [31mcol_character()[39m,
runday = [32mcol_double()[39m
)
df_uk_socdist$date %>% summary()
Min. 1st Qu. Median Mean 3rd Qu. Max.
"2020-03-01" "2020-03-08" "2020-03-16" "2020-03-16" "2020-03-24" "2020-03-31"
df_uk_socdist <- df_uk_socdist %>% select(-runday, -frequ) %>%
dplyr::rename(pers_o = open,
pers_c = sci,
pers_e = extra,
pers_a = agree,
pers_n = neuro) %>%
select(-nuts3_name) %>%
dplyr::rename(socdist_tiles = all_day_bing_tiles_visited_relat,
socdist_single_tile = all_day_ratio_single_tile_users) %>%
drop_na()
df_uk_socdist
Controls
df_uk_ctrl_nuts <- read_csv("controls_UK_nuts3.csv")
Parsed with column specification:
cols(
nuts3 = [31mcol_character()[39m,
nuts3_name = [31mcol_character()[39m,
airport_dist = [32mcol_double()[39m,
males = [32mcol_double()[39m,
popdens = [32mcol_double()[39m,
manufacturing = [32mcol_double()[39m,
tourism = [32mcol_double()[39m,
health = [32mcol_double()[39m,
academic = [32mcol_double()[39m,
medinc = [32mcol_double()[39m,
medage = [32mcol_double()[39m,
conservative = [32mcol_double()[39m
)
df_uk_ctrl_nuts <- df_uk_ctrl_nuts %>% select(-nuts3_name)
df_uk_ctrl_nuts
df_uk_ctrl_ut <- read_csv("controls_UK_ut.csv")
Parsed with column specification:
cols(
ut_area = [31mcol_character()[39m,
ut_name = [31mcol_character()[39m,
airport_dist = [32mcol_double()[39m,
males = [32mcol_double()[39m,
popdens = [32mcol_double()[39m,
manufacturing = [32mcol_double()[39m,
tourism = [32mcol_double()[39m,
health = [32mcol_double()[39m,
academic = [32mcol_double()[39m,
medinc = [32mcol_double()[39m,
medage = [32mcol_double()[39m,
conservative = [32mcol_double()[39m
)
df_uk_ctrl_ut <- df_uk_ctrl_ut %>% select(-ut_name)
df_uk_ctrl_ut
NA
NA
Merge prevalence data
df_uk_prev <- df_uk_prev %>%
plyr::join(df_uk_pers, by='ut_area') %>%
plyr::join(df_uk_ctrl_ut, by='ut_area')
# create sequence of dates
date_sequence <- seq.Date(min(df_uk_prev$date),
max(df_uk_prev$date), 1)
# create data frame with time sequence
df_dates = tibble(date_sequence, 1:length(date_sequence))
names(df_dates) <- c('date', 'time')
# merge day index with gps data
df_uk_prev = df_uk_prev %>%
merge(df_dates, by='date') %>%
arrange(ut_area) %>%
as_tibble()
df_uk_prev
Merge social distancing data
nuts_ut_key <- read_csv('nuts3_ut.csv')
Parsed with column specification:
cols(
nuts3 = [31mcol_character()[39m,
ut_area = [31mcol_character()[39m
)
df_uk_socdist <- df_uk_socdist %>% plyr::join(df_uk_ctrl_nuts, by='nuts3')
df_uk_socdist <- nuts_ut_key %>%
inner_join(df_uk_socdist, by = c('nuts3')) %>%
inner_join(select(df_uk_prev, ut_area, date, rate_day), by = c('ut_area', 'date')) %>%
select(-ut_area)
# create sequence of dates
date_sequence <- seq.Date(min(df_uk_socdist$date),
max(df_uk_socdist$date), 1)
# create data frame with time sequence
df_dates = tibble(date_sequence, 1:length(date_sequence))
names(df_dates) <- c('date', 'time')
# merge day index with gps data
df_uk_socdist = df_uk_socdist %>%
merge(df_dates, by='date') %>%
arrange(nuts3) %>%
as_tibble()
df_uk_socdist
NA
Identify London areas
nuts_london_inner <- c('UKI31','UKI32','UKI33','UKI34','UKI41',
'UKI42','UKI43','UKI44','UKI45')
nuts_london_outer <- c('UKI51','UKI52','UKI53','UKI54','UKI61',
'UKI62','UKI63','UKI71','UKI72','UKI73',
'UKI74','UKI75')
ut_london_inner <- c('E09000007','E09000001','E09000033','E09000013',
'E09000020','E09000032','E09000025','E09000012',
'E09000030','E09000014','E09000019','E09000023',
'E09000028','E09000022')
ut_london_outer <- c('E09000011','E09000004','E09000016','E09000002',
'E09000031','E09000026','E09000010','E09000006',
'E09000008','E09000029','E09000021','E09000024',
'E09000003','E09000005','E09000009','E09000017',
'E09000015','E09000018','E09000027')
df_uk_prev = df_uk_prev %>%
mutate(london = ifelse(ut_area %in% ut_london_inner, 'london_inner',
ifelse(ut_area %in% ut_london_outer, 'london_outer',
'country'))) %>%
mutate(london = as.factor(london))
df_uk_socdist = df_uk_socdist %>%
mutate(london = ifelse(nuts3 %in% nuts_london_inner, 'london_inner',
ifelse(nuts3 %in% nuts_london_outer, 'london_outer',
'country'))) %>%
mutate(london = as.factor(london))
Check timeframes
df_uk_prev$date %>% summary()
Min. 1st Qu. Median Mean 3rd Qu. Max.
"2020-01-30" "2020-02-26" "2020-03-24" "2020-03-24" "2020-04-21" "2020-05-18"
df_uk_socdist$date %>% summary()
Min. 1st Qu. Median Mean 3rd Qu. Max.
"2020-03-01" "2020-03-08" "2020-03-16" "2020-03-16" "2020-03-24" "2020-03-31"
Control for weekend effect in social distancing
df_uk_loess <- df_uk_socdist %>%
mutate(weekday = format(date, '%u')) %>%
filter(!weekday %in% c('6','7')) %>%
split(.$nuts3) %>%
map(~ loess(socdist_single_tile ~ time, data = .)) %>%
map(predict, 1:max(df_uk_socdist$time)) %>%
bind_rows() %>%
gather(key = 'nuts3', value = 'loess') %>%
group_by(nuts3) %>%
mutate(time = row_number())
df_uk_loess
df_uk_socdist <- df_uk_socdist %>% merge(df_uk_loess, by=c('nuts3', 'time')) %>%
mutate(weekday = format(date, '%u')) %>%
mutate(socdist_single_tile_clean = ifelse(weekday %in% c('6','7'), loess,
socdist_single_tile)) %>%
arrange(nuts3, time) %>%
select(-weekday)
df_uk_socdist <- df_uk_socdist %>% drop_na() %>% mutate(time = time-1)
Explore data
Plot prevalence over time
df_uk_prev %>% ggplot(aes(x=time, y=rate_day)) +
geom_point(aes(col=ut_area, size=popdens)) +
geom_smooth(method="loess", se=T) +
theme(legend.position="none") +
ggtitle("Overall prevalence over time")

pers <- c('pers_o', 'pers_c', 'pers_e', 'pers_a', 'pers_n')
for (i in pers){
gg <- df_uk_prev %>% mutate(prev_tail = cut(.[[i]],
breaks = c(-Inf, quantile(.[[i]], 0.2), quantile(.[[i]], 0.8), Inf),
labels = c('lower tail', 'center', 'upper tail'))) %>%
filter(prev_tail != 'center') %>%
ggplot(aes(x=time, y=rate_day)) +
geom_point(aes(col=ut_area, size=popdens)) +
geom_smooth(method="loess", se=T) +
facet_wrap(~prev_tail) +
theme(legend.position="none") +
ggtitle(i)
print(gg)
}





Explore differences between london and the rest
df_uk_prev %>% ggplot(aes(x=time, y=rate_day)) +
geom_point(aes(col=ut_area, size=popdens)) +
geom_smooth(method="loess", se=T) +
theme(legend.position="none") +
facet_wrap(~london) +
ggtitle("Overall prevalence over time")

NA
NA
NA
Plot social distancing over time
df_uk_socdist %>% ggplot(aes(x=time, y=socdist_single_tile_clean)) +
geom_point(aes(col=nuts3, size=popdens)) +
geom_smooth(method="loess", se=T) +
theme(legend.position="none") +
ggtitle("Overall social distancing over time")

pers <- c('pers_o', 'pers_c', 'pers_e', 'pers_a', 'pers_n')
for (i in pers){
gg <- df_uk_socdist %>% mutate(socdist_tail = cut(.[[i]],
breaks = c(-Inf, quantile(.[[i]], 0.2), quantile(.[[i]], 0.8), Inf),
labels = c('lower tail', 'center', 'upper tail'))) %>%
filter(socdist_tail != 'center') %>%
ggplot(aes(x=time, y=socdist_single_tile_clean)) +
geom_point(aes(col=nuts3, size=popdens)) +
geom_smooth(method="loess", se=T) +
facet_wrap(~socdist_tail) +
theme(legend.position="none") +
ggtitle(i)
print(gg)
}





df_uk_socdist %>% ggplot(aes(x=time, y=socdist_single_tile_clean)) +
geom_point(aes(col=nuts3, size=popdens)) +
geom_smooth(method="loess", se=T) +
theme(legend.position="none") +
facet_wrap(~london) +
ggtitle("Overall social distancing over time")

df_uk_socdist <- df_uk_socdist %>% mutate(socdist_single_tile = socdist_single_tile_clean) %>%
select(-loess, -socdist_single_tile_clean)
Correlations
df_uk_prev %>% group_by(ut_area) %>%
summarize_if(is.numeric, mean, na.rm=T) %>%
select(-ut_area, -time) %>%
cor(use = 'pairwise.complete') %>% round(3) %>%
as.data.frame()
df_uk_socdist %>% group_by(nuts3) %>%
summarize_if(is.numeric, mean, na.rm=T) %>%
select(-nuts3, -time) %>%
cor(use = 'pairwise.complete') %>% round(3) %>%
as.data.frame()
NA
Rescale Data
lvl2_scaled_ut <- df_uk_prev %>%
dplyr::select(-time, -date, -rate_day, -london) %>%
distinct() %>%
mutate_at(vars(-ut_area), scale)
lvl1_scaled_ut <- df_uk_prev %>% select(ut_area, time, rate_day)
df_uk_prev_scaled <- plyr::join(lvl1_scaled_ut, lvl2_scaled_ut, by = 'ut_area')
df_uk_prev_scaled
lvl2_scaled_nuts <- df_uk_socdist %>%
dplyr::select(-time, -date, -london,
-socdist_tiles, -socdist_single_tile, -rate_day) %>%
distinct() %>%
mutate_at(vars(-nuts3), scale)
lvl1_scaled_nuts <- df_uk_socdist %>% select(nuts3, time, socdist_single_tile, rate_day) %>%
mutate_at(vars(-nuts3, -time, - rate_day), scale)
df_uk_socdist_scaled <- plyr::join(lvl1_scaled_nuts, lvl2_scaled_nuts, by = 'nuts3')
df_uk_socdist_scaled
NA
Predict Prevalence
Explore distributions
df_uk_onset_prev %>% ggplot(aes(onset_prev)) + geom_histogram()

df_uk_slope_prev %>% ggplot(aes(slope_prev)) + geom_histogram()

Predict COVID onset with time-to-event regression
# predict onset from personality
cox_onset_prev <- coxph(Surv(onset_prev, event) ~
pers_o + pers_c + pers_e + pers_a + pers_n,
data = df_uk_onset_prev)
cox_onset_prev %>% summary()
Call:
coxph(formula = Surv(onset_prev, event) ~ pers_o + pers_c + pers_e +
pers_a + pers_n, data = df_uk_onset_prev)
n= 149, number of events= 149
coef exp(coef) se(coef) z Pr(>|z|)
pers_o 0.322264 1.380249 0.166864 1.931 0.0534 .
pers_c 0.036475 1.037149 0.135119 0.270 0.7872
pers_e -0.013895 0.986201 0.143396 -0.097 0.9228
pers_a 0.005323 1.005338 0.106927 0.050 0.9603
pers_n -0.092400 0.911740 0.106197 -0.870 0.3843
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
exp(coef) exp(-coef) lower .95 upper .95
pers_o 1.3802 0.7245 0.9952 1.914
pers_c 1.0371 0.9642 0.7958 1.352
pers_e 0.9862 1.0140 0.7446 1.306
pers_a 1.0053 0.9947 0.8153 1.240
pers_n 0.9117 1.0968 0.7404 1.123
Concordance= 0.605 (se = 0.027 )
Likelihood ratio test= 12.64 on 5 df, p=0.03
Wald test = 13.47 on 5 df, p=0.02
Score (logrank) test = 13.78 on 5 df, p=0.02
# predict onset from personality with controls
cox_onset_prev_ctrl <- coxph(Surv(onset_prev, event) ~
pers_o + pers_c + pers_e + pers_a + pers_n +
airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage +
conservative,
data = df_uk_onset_prev)
cox_onset_prev_ctrl %>% summary()
Call:
coxph(formula = Surv(onset_prev, event) ~ pers_o + pers_c + pers_e +
pers_a + pers_n + airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage + conservative,
data = df_uk_onset_prev)
n= 144, number of events= 144
(5 observations deleted due to missingness)
coef exp(coef) se(coef) z Pr(>|z|)
pers_o 0.13431 1.14375 0.26537 0.506 0.6128
pers_c 0.27571 1.31746 0.21410 1.288 0.1978
pers_e -0.28546 0.75167 0.16166 -1.766 0.0774 .
pers_a 0.15618 1.16904 0.12936 1.207 0.2273
pers_n -0.04289 0.95801 0.13821 -0.310 0.7563
airport_dist 0.08819 1.09219 0.10241 0.861 0.3892
males -0.28751 0.75013 0.11525 -2.495 0.0126 *
popdens 0.31764 1.37388 0.22294 1.425 0.1542
manufacturing -0.01434 0.98576 0.15053 -0.095 0.9241
tourism 0.20101 1.22263 0.12897 1.559 0.1191
health -0.13046 0.87769 0.09930 -1.314 0.1889
academic 0.41323 1.51170 0.25879 1.597 0.1103
medinc -0.10312 0.90201 0.15281 -0.675 0.4998
medage -0.54104 0.58214 0.21413 -2.527 0.0115 *
conservative -0.05175 0.94957 0.28447 -0.182 0.8557
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
exp(coef) exp(-coef) lower .95 upper .95
pers_o 1.1438 0.8743 0.6799 1.9241
pers_c 1.3175 0.7590 0.8660 2.0044
pers_e 0.7517 1.3304 0.5475 1.0319
pers_a 1.1690 0.8554 0.9072 1.5064
pers_n 0.9580 1.0438 0.7307 1.2561
airport_dist 1.0922 0.9156 0.8936 1.3350
males 0.7501 1.3331 0.5985 0.9402
popdens 1.3739 0.7279 0.8875 2.1267
manufacturing 0.9858 1.0144 0.7339 1.3240
tourism 1.2226 0.8179 0.9496 1.5742
health 0.8777 1.1394 0.7225 1.0663
academic 1.5117 0.6615 0.9103 2.5104
medinc 0.9020 1.1086 0.6686 1.2170
medage 0.5821 1.7178 0.3826 0.8857
conservative 0.9496 1.0531 0.5437 1.6583
Concordance= 0.643 (se = 0.027 )
Likelihood ratio test= 37.26 on 15 df, p=0.001
Wald test = 39.13 on 15 df, p=6e-04
Score (logrank) test = 40.98 on 15 df, p=3e-04
Predict prevalence slopes with linear models
# predict slopes from personality
lm_slope_prev <- lm(slope_prev ~ pers_o + pers_c + pers_e + pers_a + pers_n,
data = df_uk_slope_prev)
lm_slope_prev %>% summary()
Call:
lm(formula = slope_prev ~ pers_o + pers_c + pers_e + pers_a +
pers_n, data = df_uk_slope_prev)
Residuals:
Min 1Q Median 3Q Max
-0.032324 -0.011515 -0.003789 0.012728 0.048348
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.0239193 0.0014399 16.612 < 2e-16 ***
pers_o -0.0060442 0.0028372 -2.130 0.03492 *
pers_c -0.0074351 0.0023785 -3.126 0.00216 **
pers_e 0.0033599 0.0026519 1.267 0.20731
pers_a -0.0014460 0.0020483 -0.706 0.48139
pers_n -0.0001847 0.0021315 -0.087 0.93109
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.01727 on 138 degrees of freedom
Multiple R-squared: 0.121, Adjusted R-squared: 0.0892
F-statistic: 3.801 on 5 and 138 DF, p-value: 0.002952
# predict slopes from personality with controls
lm_slope_prev_ctrl <- lm(slope_prev ~
pers_o + pers_c + pers_e + pers_a + pers_n +
airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage +
conservative,
data = df_uk_slope_prev)
lm_slope_prev_ctrl %>% summary()
Call:
lm(formula = slope_prev ~ pers_o + pers_c + pers_e + pers_a +
pers_n + airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage + conservative,
data = df_uk_slope_prev)
Residuals:
Min 1Q Median 3Q Max
-0.028137 -0.010922 -0.002334 0.009211 0.045494
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 2.388e-02 1.380e-03 17.303 <2e-16 ***
pers_o -3.760e-03 4.133e-03 -0.910 0.3648
pers_c -7.549e-03 3.233e-03 -2.335 0.0211 *
pers_e 1.386e-03 2.733e-03 0.507 0.6128
pers_a 4.417e-04 2.399e-03 0.184 0.8542
pers_n -1.024e-03 2.440e-03 -0.419 0.6756
airport_dist -4.622e-03 1.818e-03 -2.542 0.0122 *
males -1.683e-03 2.049e-03 -0.821 0.4131
popdens 6.486e-03 3.510e-03 1.848 0.0669 .
manufacturing 8.049e-05 2.368e-03 0.034 0.9729
tourism -8.124e-04 2.007e-03 -0.405 0.6863
health 1.847e-03 1.739e-03 1.062 0.2904
academic -8.043e-04 4.209e-03 -0.191 0.8488
medinc 3.966e-03 2.549e-03 1.556 0.1221
medage 4.778e-03 3.375e-03 1.416 0.1593
conservative 5.636e-03 4.576e-03 1.231 0.2204
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.01653 on 128 degrees of freedom
Multiple R-squared: 0.253, Adjusted R-squared: 0.1655
F-statistic: 2.89 on 15 and 128 DF, p-value: 0.0006055
CRF predicting slopes
ctrls <- cforest_unbiased(ntree=500, mtry=5)
crf_slope_prev <- cforest(slope_prev ~
pers_o + pers_c + pers_e + pers_a + pers_n +
airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage +
conservative,
data = df_uk_slope_prev,
controls = ctrls)
crf_slope_prev_varimp <- varimp(crf_slope_prev, nperm = 1)
crf_slope_prev_varimp_cond <- varimp(crf_slope_prev, conditional = T, nperm = 1)
crf_slope_prev_varimp %>% as.data.frame() %>%
rownames_to_column('variable') %>%
ggplot(aes(x=variable, y=.)) +
geom_bar(stat = 'identity') +
theme(axis.text.x = element_text(angle = 90))

crf_slope_prev_varimp_cond %>% as.data.frame() %>%
rownames_to_column('variable') %>%
ggplot(aes(x=variable, y=.)) +
geom_bar(stat = 'identity') +
theme(axis.text.x = element_text(angle = 90))

Predict Social Distancing
Change point analysis
# keep only counties with full data
nuts_complete <- df_uk_socdist_scaled %>%
group_by(nuts3) %>%
summarize(n = n()) %>%
filter(n==max(.$n)) %>%
.$nuts3
# run changepoint analysis
df_uk_socdist_cpt_results <- df_uk_socdist_scaled %>%
select(nuts3, socdist_single_tile) %>%
filter(nuts3 %in% nuts_complete) %>%
split(.$nuts3) %>%
map(~ cpt.meanvar(as.vector(.$socdist_single_tile),
#penalty = 'Asymptotic',
class=TRUE,
param.estimates=TRUE,
Q=1,
test.stat = 'Normal'))
# calculate change point
df_uk_socdist_cpt_day <- df_uk_socdist_cpt_results %>%
map(cpts) %>%
unlist() %>%
as.data.frame() %>%
rename(cpt_day_socdist = '.') %>%
rownames_to_column('nuts3')
# calculate mean differences
df_uk_socdist_cpt_mean_diff <- df_uk_socdist_cpt_results %>%
map(param.est) %>%
map(~ .$mean) %>%
map(~ .[2]-.[1]) %>%
unlist() %>%
as.data.frame() %>%
rename(mean_diff_socdist = '.') %>%
rownames_to_column('nuts3')
# calculate varaince differences
df_uk_socdist_cpt_var_diff <- df_uk_socdist_cpt_results %>%
map(param.est) %>%
map(~ .$variance) %>%
map(~ .[2]-.[1]) %>%
unlist() %>%
as.data.frame() %>%
rename(var_diff_socdist = '.') %>%
rownames_to_column('nuts3')
# merge with county data
df_uk_cpt_socdist <- df_uk_socdist_scaled %>%
select(-time, -rate_day, -socdist_single_tile) %>%
distinct() %>%
left_join(df_uk_socdist_cpt_day, by='nuts3') %>%
left_join(df_uk_socdist_cpt_mean_diff, by='nuts3') %>%
left_join(df_uk_socdist_cpt_var_diff, by='nuts3') %>%
left_join(nuts_ut_key, by='nuts3') %>%
left_join(select(df_uk_onset_prev, ut_area, onset_prev), by='ut_area') %>%
left_join(select(df_uk_slope_prev, ut_area, slope_prev), by='ut_area') %>%
select(-ut_area)
# handle censored data
df_uk_cpt_socdist <- df_uk_cpt_socdist %>%
mutate(cpt_day_socdist = ifelse(is.na(cpt_day_socdist),
as.numeric(diff(range(df_us$date))),
cpt_day_socdist)) %>%
mutate(event = ifelse(cpt_day_socdist >= 60, 0, 1))
df_uk_cpt_socdist$cpt_day_socdist %>% hist()

df_uk_cpt_socdist$mean_diff_socdist %>% hist()

df_uk_cpt_socdist$var_diff_socdist %>% hist()

for(i in head(df_uk_socdist_cpt_results, 5)){
plot(i)
}




NA

Predicting change points with time-to-event regression
# predict hazard from personality
cox_cpt_socdist <- coxph(Surv(cpt_day_socdist, event) ~
pers_o + pers_c + pers_e + pers_a + pers_n,
data = df_uk_cpt_socdist)
cox_cpt_socdist %>% summary()
Call:
coxph(formula = Surv(cpt_day_socdist, event) ~ pers_o + pers_c +
pers_e + pers_a + pers_n, data = df_uk_cpt_socdist)
n= 131, number of events= 131
coef exp(coef) se(coef) z Pr(>|z|)
pers_o 0.02292 1.02319 0.14906 0.154 0.878
pers_c 0.01178 1.01185 0.14322 0.082 0.934
pers_e 0.17493 1.19117 0.14723 1.188 0.235
pers_a -0.19324 0.82428 0.11907 -1.623 0.105
pers_n -0.01502 0.98509 0.12389 -0.121 0.903
exp(coef) exp(-coef) lower .95 upper .95
pers_o 1.0232 0.9773 0.7640 1.370
pers_c 1.0118 0.9883 0.7642 1.340
pers_e 1.1912 0.8395 0.8926 1.590
pers_a 0.8243 1.2132 0.6527 1.041
pers_n 0.9851 1.0151 0.7727 1.256
Concordance= 0.672 (se = 0.046 )
Likelihood ratio test= 11.4 on 5 df, p=0.04
Wald test = 13.38 on 5 df, p=0.02
Score (logrank) test = 13.55 on 5 df, p=0.02
# predict hazard from personality with controls
cox_cpt_socdist_ctrl <- coxph(Surv(cpt_day_socdist, event) ~
pers_o + pers_c + pers_e + pers_a + pers_n +
airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage +
conservative,
data = df_uk_cpt_socdist)
cox_cpt_socdist_ctrl %>% summary()
Call:
coxph(formula = Surv(cpt_day_socdist, event) ~ pers_o + pers_c +
pers_e + pers_a + pers_n + airport_dist + males + popdens +
manufacturing + tourism + health + academic + medinc + medage +
conservative, data = df_uk_cpt_socdist)
n= 131, number of events= 131
coef exp(coef) se(coef) z Pr(>|z|)
pers_o -0.100979 0.903952 0.243690 -0.414 0.6786
pers_c -0.048635 0.952528 0.198550 -0.245 0.8065
pers_e 0.080996 1.084366 0.163732 0.495 0.6208
pers_a -0.006914 0.993110 0.162410 -0.043 0.9660
pers_n 0.204498 1.226909 0.151016 1.354 0.1757
airport_dist 0.251102 1.285441 0.126736 1.981 0.0476 *
males -0.148267 0.862201 0.142494 -1.041 0.2981
popdens 0.158406 1.171641 0.233680 0.678 0.4979
manufacturing -0.083042 0.920313 0.130937 -0.634 0.5259
tourism -0.254837 0.775043 0.142800 -1.785 0.0743 .
health -0.266804 0.765823 0.122195 -2.183 0.0290 *
academic 0.153738 1.166185 0.247465 0.621 0.5344
medinc 0.166816 1.181537 0.177460 0.940 0.3472
medage -0.008602 0.991435 0.216020 -0.040 0.9682
conservative -0.180652 0.834726 0.268518 -0.673 0.5011
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
exp(coef) exp(-coef) lower .95 upper .95
pers_o 0.9040 1.1063 0.5607 1.4574
pers_c 0.9525 1.0498 0.6455 1.4057
pers_e 1.0844 0.9222 0.7867 1.4947
pers_a 0.9931 1.0069 0.7224 1.3653
pers_n 1.2269 0.8151 0.9126 1.6495
airport_dist 1.2854 0.7779 1.0027 1.6479
males 0.8622 1.1598 0.6521 1.1400
popdens 1.1716 0.8535 0.7411 1.8523
manufacturing 0.9203 1.0866 0.7120 1.1896
tourism 0.7750 1.2903 0.5858 1.0254
health 0.7658 1.3058 0.6027 0.9731
academic 1.1662 0.8575 0.7180 1.8941
medinc 1.1815 0.8464 0.8344 1.6730
medage 0.9914 1.0086 0.6492 1.5141
conservative 0.8347 1.1980 0.4932 1.4129
Concordance= 0.756 (se = 0.043 )
Likelihood ratio test= 30.64 on 15 df, p=0.01
Wald test = 31.24 on 15 df, p=0.008
Score (logrank) test = 32.93 on 15 df, p=0.005
# predict hazard from personality with controls
cox_cpt_socdist_ctrl2 <- coxph(Surv(cpt_day_socdist, event) ~
pers_o + pers_c + pers_e + pers_a + pers_n +
airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage +
conservative + onset_prev + slope_prev,
data = df_uk_cpt_socdist)
cox_cpt_socdist_ctrl2 %>% summary()
Call:
coxph(formula = Surv(cpt_day_socdist, event) ~ pers_o + pers_c +
pers_e + pers_a + pers_n + airport_dist + males + popdens +
manufacturing + tourism + health + academic + medinc + medage +
conservative + onset_prev + slope_prev, data = df_uk_cpt_socdist)
n= 130, number of events= 130
(1 observation deleted due to missingness)
coef exp(coef) se(coef) z Pr(>|z|)
pers_o -1.002e-01 9.046e-01 2.493e-01 -0.402 0.6877
pers_c -1.163e-01 8.902e-01 2.070e-01 -0.562 0.5742
pers_e 8.183e-02 1.085e+00 1.631e-01 0.502 0.6158
pers_a 5.279e-02 1.054e+00 1.731e-01 0.305 0.7604
pers_n 2.313e-01 1.260e+00 1.571e-01 1.472 0.1411
airport_dist 2.164e-01 1.242e+00 1.291e-01 1.676 0.0936 .
males -2.161e-01 8.057e-01 1.560e-01 -1.385 0.1661
popdens 3.186e-01 1.375e+00 2.541e-01 1.254 0.2098
manufacturing -6.886e-02 9.335e-01 1.314e-01 -0.524 0.6003
tourism -2.531e-01 7.764e-01 1.447e-01 -1.749 0.0803 .
health -2.746e-01 7.599e-01 1.267e-01 -2.167 0.0302 *
academic 7.433e-02 1.077e+00 2.554e-01 0.291 0.7711
medinc 2.756e-01 1.317e+00 1.876e-01 1.469 0.1419
medage 4.406e-02 1.045e+00 2.175e-01 0.203 0.8395
conservative -1.681e-01 8.453e-01 2.693e-01 -0.624 0.5324
onset_prev -1.956e-03 9.980e-01 1.470e-02 -0.133 0.8941
slope_prev -1.053e+01 2.674e-05 9.175e+00 -1.148 0.2511
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
exp(coef) exp(-coef) lower .95 upper .95
pers_o 9.046e-01 1.105e+00 5.550e-01 1.4745
pers_c 8.902e-01 1.123e+00 5.933e-01 1.3356
pers_e 1.085e+00 9.214e-01 7.884e-01 1.4940
pers_a 1.054e+00 9.486e-01 7.509e-01 1.4801
pers_n 1.260e+00 7.935e-01 9.261e-01 1.7148
airport_dist 1.242e+00 8.054e-01 9.641e-01 1.5990
males 8.057e-01 1.241e+00 5.934e-01 1.0939
popdens 1.375e+00 7.271e-01 8.358e-01 2.2628
manufacturing 9.335e-01 1.071e+00 7.215e-01 1.2077
tourism 7.764e-01 1.288e+00 5.846e-01 1.0310
health 7.599e-01 1.316e+00 5.927e-01 0.9741
academic 1.077e+00 9.284e-01 6.529e-01 1.7771
medinc 1.317e+00 7.591e-01 9.120e-01 1.9027
medage 1.045e+00 9.569e-01 6.823e-01 1.6007
conservative 8.453e-01 1.183e+00 4.986e-01 1.4328
onset_prev 9.980e-01 1.002e+00 9.697e-01 1.0272
slope_prev 2.674e-05 3.740e+04 4.145e-13 1724.8956
Concordance= 0.745 (se = 0.044 )
Likelihood ratio test= 32.6 on 17 df, p=0.01
Wald test = 32.53 on 17 df, p=0.01
Score (logrank) test = 33.98 on 17 df, p=0.008
Linear models predicting mean differences
lm_meandiff_socdist <- lm(mean_diff_socdist ~
pers_o + pers_c + pers_e + pers_a + pers_n,
data = df_uk_cpt_socdist)
lm_meandiff_socdist %>% summary()
Call:
lm(formula = mean_diff_socdist ~ pers_o + pers_c + pers_e + pers_a +
pers_n, data = df_uk_cpt_socdist)
Residuals:
Min 1Q Median 3Q Max
-0.236161 -0.073887 -0.001491 0.063529 0.288673
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.617663 0.009637 167.864 < 2e-16 ***
pers_o -0.004645 0.017588 -0.264 0.792145
pers_c -0.039209 0.016089 -2.437 0.016220 *
pers_e 0.059962 0.017020 3.523 0.000596 ***
pers_a -0.020685 0.014162 -1.461 0.146648
pers_n -0.004006 0.014038 -0.285 0.775854
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.1103 on 125 degrees of freedom
Multiple R-squared: 0.4319, Adjusted R-squared: 0.4092
F-statistic: 19.01 on 5 and 125 DF, p-value: 5.03e-14
lm_meandiff_socdist_ctrl <- lm(mean_diff_socdist ~
pers_o + pers_c + pers_e + pers_a + pers_n +
airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage +
conservative,
data = df_uk_cpt_socdist)
lm_meandiff_socdist_ctrl %>% summary()
Call:
lm(formula = mean_diff_socdist ~ pers_o + pers_c + pers_e + pers_a +
pers_n + airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage + conservative,
data = df_uk_cpt_socdist)
Residuals:
Min 1Q Median 3Q Max
-0.240455 -0.063142 -0.001388 0.051147 0.206542
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.6176625 0.0075553 214.109 < 2e-16 ***
pers_o -0.0326846 0.0220339 -1.483 0.1407
pers_c -0.0130620 0.0177712 -0.735 0.4638
pers_e 0.0120006 0.0146614 0.819 0.4148
pers_a 0.0360106 0.0140066 2.571 0.0114 *
pers_n 0.0229335 0.0122311 1.875 0.0633 .
airport_dist -0.0208327 0.0106569 -1.955 0.0530 .
males -0.0256885 0.0125746 -2.043 0.0434 *
popdens 0.0928652 0.0197043 4.713 6.9e-06 ***
manufacturing -0.0252661 0.0117189 -2.156 0.0332 *
tourism -0.0103949 0.0112219 -0.926 0.3562
health -0.0005235 0.0099268 -0.053 0.9580
academic 0.0282827 0.0220672 1.282 0.2025
medinc 0.0263085 0.0145454 1.809 0.0731 .
medage -0.0012929 0.0193857 -0.067 0.9469
conservative -0.0049255 0.0247582 -0.199 0.8427
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.08647 on 115 degrees of freedom
Multiple R-squared: 0.6787, Adjusted R-squared: 0.6368
F-statistic: 16.2 on 15 and 115 DF, p-value: < 2.2e-16
lm_meandiff_socdist_ctrl2 <- lm(mean_diff_socdist ~
pers_o + pers_c + pers_e + pers_a + pers_n +
airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage +
conservative + onset_prev + slope_prev,
data = df_uk_cpt_socdist)
lm_meandiff_socdist_ctrl2 %>% summary()
Call:
lm(formula = mean_diff_socdist ~ pers_o + pers_c + pers_e + pers_a +
pers_n + airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage + conservative +
onset_prev + slope_prev, data = df_uk_cpt_socdist)
Residuals:
Min 1Q Median 3Q Max
-0.248333 -0.059558 0.000339 0.056215 0.216795
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.6305244 0.0318952 51.121 < 2e-16 ***
pers_o -0.0353915 0.0223396 -1.584 0.1160
pers_c -0.0090910 0.0179360 -0.507 0.6133
pers_e 0.0125871 0.0146878 0.857 0.3933
pers_a 0.0357278 0.0140017 2.552 0.0121 *
pers_n 0.0218672 0.0122562 1.784 0.0771 .
airport_dist -0.0178000 0.0107886 -1.650 0.1018
males -0.0179556 0.0133454 -1.345 0.1812
popdens 0.0859734 0.0206309 4.167 6.09e-05 ***
manufacturing -0.0261575 0.0118566 -2.206 0.0294 *
tourism -0.0110823 0.0112664 -0.984 0.3274
health -0.0008650 0.0099392 -0.087 0.9308
academic 0.0283153 0.0222260 1.274 0.2053
medinc 0.0214989 0.0148569 1.447 0.1507
medage -0.0004348 0.0194895 -0.022 0.9822
conservative -0.0078513 0.0247978 -0.317 0.7521
onset_prev -0.0012086 0.0011796 -1.025 0.3078
slope_prev 1.2542002 0.6996823 1.793 0.0757 .
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.08639 on 112 degrees of freedom
(1 observation deleted due to missingness)
Multiple R-squared: 0.6857, Adjusted R-squared: 0.638
F-statistic: 14.38 on 17 and 112 DF, p-value: < 2.2e-16
CRF predicting mean difference
ctrls <- cforest_unbiased(ntree=500, mtry=5)
crf_meandiff_socdist <- cforest(mean_diff_socdist ~
pers_o + pers_c + pers_e + pers_a + pers_n +
airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage +
conservative + onset_prev + slope_prev,
data = df_uk_cpt_socdist %>% drop_na(),
controls = ctrls)
crf_meandiff_socdist_varimp <- varimp(crf_meandiff_socdist, nperm = 1)
crf_meandiff_socdist_varimp_cond <- varimp(crf_meandiff_socdist, conditional = T, nperm = 1)
crf_meandiff_socdist_varimp %>% as.data.frame() %>%
rownames_to_column('variable') %>%
ggplot(aes(x=variable, y=.)) +
geom_bar(stat = 'identity') +
theme(axis.text.x = element_text(angle = 90))

crf_meandiff_socdist_varimp_cond %>% as.data.frame() %>%
rownames_to_column('variable') %>%
ggplot(aes(x=variable, y=.)) +
geom_bar(stat = 'identity') +
theme(axis.text.x = element_text(angle = 90))

LS0tCnRpdGxlOiAiQ09WSUQxOSBVSyIKYXV0aG9yOiAiSGVpbnJpY2ggUGV0ZXJzIgpkYXRlOiAiNC8yMy8yMDIwIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKCiMgTUFDCiBrbml0cjo6b3B0c19rbml0JHNldChyb290LmRpciA9ICcvVXNlcnMvaHAyNTAwL0dvb2dsZSBEcml2ZS9TVFVEWS9Db2x1bWJpYS9SZXNlYXJjaC9Db3JvbmEvRGF0YS9VSycpCiAKbGlicmFyeShsbWVyVGVzdCkKbGlicmFyeShubG1lKQpsaWJyYXJ5KHBzeWNoKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHBhcnR5KQpsaWJyYXJ5KGRvUGFyYWxsZWwpCmxpYnJhcnkoY2hhbmdlcG9pbnQpCmxpYnJhcnkoc3Vydml2YWwpCmxpYnJhcnkoc3Vydm1pbmVyKQoKYGBgCgojIFByZXBhcmUgZGF0YQoKIyMjIFJlYWQgYW5kIGZvcm1hdCBkYXRhCgojIyMgUHJldmFsZW5jZSAKCmBgYHtyfQpkZl91a19wcmV2IDwtIHJlYWRfY3N2KCdVS190aW1lc2VyaWVzX3ByZXBfMjAwNS5jc3YnKQoKZGZfdWtfcHJldiA8LSBkZl91a19wcmV2ICU+JSAKICBzZWxlY3QodXRfYXJlYSwgZGF0ZSwgcmF0ZSkgJT4lIAogIHJlbmFtZShyYXRlX2RheSA9IHJhdGUpICU+JQogIG11dGF0ZShkYXRlID0gYXMuRGF0ZShkYXRlLCAiJWQlYiVZIikpCgpkZl91a19wcmV2CmBgYAoKIyMjIFBlcnNvbmFsaXR5CmBgYHtyfQoKZGZfdWtfcGVycyA8LSByZWFkX2NzdigndGltZXNlcmllc191a191dGxhX21hcmNoOV9hcHJpbF8wOS5jc3YnKQoKZGZfdWtfcGVycyA8LSBkZl91a19wZXJzICU+JSAKICBzZWxlY3QodXRfYXJlYSwgb3BlbiwgYWdyZWUsIG5ldXJvLCBzY2ksIGV4dHJhKSAlPiUgCiAgZHBseXI6OnJlbmFtZShwZXJzX28gPSBvcGVuLCAKICAgICAgICAgcGVyc19jID0gc2NpLAogICAgICAgICBwZXJzX2UgPSBleHRyYSwKICAgICAgICAgcGVyc19hID0gYWdyZWUsCiAgICAgICAgIHBlcnNfbiA9IG5ldXJvKSAlPiUKICBkaXN0aW5jdCgpCgpkZl91a19wZXJzCgpgYGAKCiMjIyBTb2NpYWwgZGlzdGFuY2luZwpgYGB7cn0KZGZfdWtfc29jZGlzdCA8LSByZWFkX2NzdignVUtfc29jZGlzdF9mYl9udXRzMy5jc3YnKQpkZl91a19zb2NkaXN0JGRhdGUgJT4lIHN1bW1hcnkoKQoKZGZfdWtfc29jZGlzdCA8LSBkZl91a19zb2NkaXN0ICU+JSBzZWxlY3QoLXJ1bmRheSwgLWZyZXF1KSAlPiUKICBkcGx5cjo6cmVuYW1lKHBlcnNfbyA9IG9wZW4sIAogICAgICAgICAgICAgICAgcGVyc19jID0gc2NpLAogICAgICAgICAgICAgICAgcGVyc19lID0gZXh0cmEsCiAgICAgICAgICAgICAgICBwZXJzX2EgPSBhZ3JlZSwKICAgICAgICAgICAgICAgIHBlcnNfbiA9IG5ldXJvKSAlPiUgCiAgc2VsZWN0KC1udXRzM19uYW1lKSAlPiUgCiAgZHBseXI6OnJlbmFtZShzb2NkaXN0X3RpbGVzID0gYWxsX2RheV9iaW5nX3RpbGVzX3Zpc2l0ZWRfcmVsYXQsCiAgICAgICAgICAgICAgICBzb2NkaXN0X3NpbmdsZV90aWxlID0gYWxsX2RheV9yYXRpb19zaW5nbGVfdGlsZV91c2VycykgJT4lCiAgZHJvcF9uYSgpCgpkZl91a19zb2NkaXN0CmBgYAoKIyMjIENvbnRyb2xzIApgYGB7cn0KZGZfdWtfY3RybF9udXRzIDwtIHJlYWRfY3N2KCJjb250cm9sc19VS19udXRzMy5jc3YiKQpkZl91a19jdHJsX251dHMgPC0gZGZfdWtfY3RybF9udXRzICU+JSBzZWxlY3QoLW51dHMzX25hbWUpCmRmX3VrX2N0cmxfbnV0cwoKCmRmX3VrX2N0cmxfdXQgPC0gcmVhZF9jc3YoImNvbnRyb2xzX1VLX3V0LmNzdiIpCmRmX3VrX2N0cmxfdXQgPC0gZGZfdWtfY3RybF91dCAlPiUgc2VsZWN0KC11dF9uYW1lKQpkZl91a19jdHJsX3V0CgoKYGBgCgoKCgoKIyMjIE1lcmdlIHByZXZhbGVuY2UgZGF0YSAKYGBge3J9CmRmX3VrX3ByZXYgPC0gZGZfdWtfcHJldiAlPiUgCiAgcGx5cjo6am9pbihkZl91a19wZXJzLCBieT0ndXRfYXJlYScpICU+JSAKICBwbHlyOjpqb2luKGRmX3VrX2N0cmxfdXQsIGJ5PSd1dF9hcmVhJykKCiMgY3JlYXRlIHNlcXVlbmNlIG9mIGRhdGVzCmRhdGVfc2VxdWVuY2UgPC0gc2VxLkRhdGUobWluKGRmX3VrX3ByZXYkZGF0ZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4KGRmX3VrX3ByZXYkZGF0ZSksIDEpCiAgICAgICAgICAgICAgICAgICAgIAojIGNyZWF0ZSBkYXRhIGZyYW1lIHdpdGggdGltZSBzZXF1ZW5jZQpkZl9kYXRlcyA9IHRpYmJsZShkYXRlX3NlcXVlbmNlLCAxOmxlbmd0aChkYXRlX3NlcXVlbmNlKSkgCm5hbWVzKGRmX2RhdGVzKSA8LSBjKCdkYXRlJywgJ3RpbWUnKQoKIyBtZXJnZSBkYXkgaW5kZXggd2l0aCBncHMgZGF0YQpkZl91a19wcmV2ID0gZGZfdWtfcHJldiAlPiUgCiAgbWVyZ2UoZGZfZGF0ZXMsIGJ5PSdkYXRlJykgJT4lIAogIGFycmFuZ2UodXRfYXJlYSkgJT4lCiAgYXNfdGliYmxlKCkKCmRmX3VrX3ByZXYKYGBgCgojIyMgTWVyZ2Ugc29jaWFsIGRpc3RhbmNpbmcgZGF0YQpgYGB7cn0KCm51dHNfdXRfa2V5IDwtIHJlYWRfY3N2KCdudXRzM191dC5jc3YnKQpkZl91a19zb2NkaXN0IDwtIGRmX3VrX3NvY2Rpc3QgJT4lIHBseXI6OmpvaW4oZGZfdWtfY3RybF9udXRzLCBieT0nbnV0czMnKQoKZGZfdWtfc29jZGlzdCA8LSBudXRzX3V0X2tleSAlPiUgCiAgaW5uZXJfam9pbihkZl91a19zb2NkaXN0LCBieSA9IGMoJ251dHMzJykpICU+JQogIGlubmVyX2pvaW4oc2VsZWN0KGRmX3VrX3ByZXYsIHV0X2FyZWEsIGRhdGUsIHJhdGVfZGF5KSwgYnkgPSBjKCd1dF9hcmVhJywgJ2RhdGUnKSkgJT4lCiAgc2VsZWN0KC11dF9hcmVhKQoKIyBjcmVhdGUgc2VxdWVuY2Ugb2YgZGF0ZXMKZGF0ZV9zZXF1ZW5jZSA8LSBzZXEuRGF0ZShtaW4oZGZfdWtfc29jZGlzdCRkYXRlKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBtYXgoZGZfdWtfc29jZGlzdCRkYXRlKSwgMSkKICAgICAgICAgICAgICAgICAgICAgCiMgY3JlYXRlIGRhdGEgZnJhbWUgd2l0aCB0aW1lIHNlcXVlbmNlCmRmX2RhdGVzID0gdGliYmxlKGRhdGVfc2VxdWVuY2UsIDE6bGVuZ3RoKGRhdGVfc2VxdWVuY2UpKSAKbmFtZXMoZGZfZGF0ZXMpIDwtIGMoJ2RhdGUnLCAndGltZScpCgojIG1lcmdlIGRheSBpbmRleCB3aXRoIGdwcyBkYXRhCmRmX3VrX3NvY2Rpc3QgPSBkZl91a19zb2NkaXN0ICU+JSAKICBtZXJnZShkZl9kYXRlcywgYnk9J2RhdGUnKSAlPiUgCiAgYXJyYW5nZShudXRzMykgJT4lCiAgYXNfdGliYmxlKCkKCgpkZl91a19zb2NkaXN0CgpgYGAKCiMjIyBJZGVudGlmeSBMb25kb24gYXJlYXMKYGBge3J9CgpudXRzX2xvbmRvbl9pbm5lciA8LSBjKCdVS0kzMScsJ1VLSTMyJywnVUtJMzMnLCdVS0kzNCcsJ1VLSTQxJywKICAgICAgICAgICAgICAgICAgICAgICdVS0k0MicsJ1VLSTQzJywnVUtJNDQnLCdVS0k0NScpCgpudXRzX2xvbmRvbl9vdXRlciA8LSBjKCdVS0k1MScsJ1VLSTUyJywnVUtJNTMnLCdVS0k1NCcsJ1VLSTYxJywKICAgICAgICAgICAgICAgICAgICAgICdVS0k2MicsJ1VLSTYzJywnVUtJNzEnLCdVS0k3MicsJ1VLSTczJywKICAgICAgICAgICAgICAgICAgICAgICdVS0k3NCcsJ1VLSTc1JykKCnV0X2xvbmRvbl9pbm5lciA8LSBjKCdFMDkwMDAwMDcnLCdFMDkwMDAwMDEnLCdFMDkwMDAwMzMnLCdFMDkwMDAwMTMnLAogICAgICAgICAgICAgICAgICAgICdFMDkwMDAwMjAnLCdFMDkwMDAwMzInLCdFMDkwMDAwMjUnLCdFMDkwMDAwMTInLAogICAgICAgICAgICAgICAgICAgICdFMDkwMDAwMzAnLCdFMDkwMDAwMTQnLCdFMDkwMDAwMTknLCdFMDkwMDAwMjMnLAogICAgICAgICAgICAgICAgICAgICdFMDkwMDAwMjgnLCdFMDkwMDAwMjInKQoKdXRfbG9uZG9uX291dGVyIDwtIGMoJ0UwOTAwMDAxMScsJ0UwOTAwMDAwNCcsJ0UwOTAwMDAxNicsJ0UwOTAwMDAwMicsCiAgICAgICAgICAgICAgICAgICAgJ0UwOTAwMDAzMScsJ0UwOTAwMDAyNicsJ0UwOTAwMDAxMCcsJ0UwOTAwMDAwNicsCiAgICAgICAgICAgICAgICAgICAgJ0UwOTAwMDAwOCcsJ0UwOTAwMDAyOScsJ0UwOTAwMDAyMScsJ0UwOTAwMDAyNCcsCiAgICAgICAgICAgICAgICAgICAgJ0UwOTAwMDAwMycsJ0UwOTAwMDAwNScsJ0UwOTAwMDAwOScsJ0UwOTAwMDAxNycsCiAgICAgICAgICAgICAgICAgICAgJ0UwOTAwMDAxNScsJ0UwOTAwMDAxOCcsJ0UwOTAwMDAyNycpCmBgYAoKYGBge3J9CgpkZl91a19wcmV2ID0gZGZfdWtfcHJldiAlPiUgCiAgbXV0YXRlKGxvbmRvbiA9IGlmZWxzZSh1dF9hcmVhICVpbiUgdXRfbG9uZG9uX2lubmVyLCAnbG9uZG9uX2lubmVyJywgCiAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHV0X2FyZWEgJWluJSB1dF9sb25kb25fb3V0ZXIsICdsb25kb25fb3V0ZXInLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY291bnRyeScpKSkgJT4lCiAgbXV0YXRlKGxvbmRvbiA9IGFzLmZhY3Rvcihsb25kb24pKQoKZGZfdWtfc29jZGlzdCA9IGRmX3VrX3NvY2Rpc3QgJT4lIAogIG11dGF0ZShsb25kb24gPSBpZmVsc2UobnV0czMgJWluJSBudXRzX2xvbmRvbl9pbm5lciwgJ2xvbmRvbl9pbm5lcicsIAogICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShudXRzMyAlaW4lIG51dHNfbG9uZG9uX291dGVyLCAnbG9uZG9uX291dGVyJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NvdW50cnknKSkpICU+JQogIG11dGF0ZShsb25kb24gPSBhcy5mYWN0b3IobG9uZG9uKSkKCmBgYAoKIyMjIENoZWNrIHRpbWVmcmFtZXMgCmBgYHtyfQpkZl91a19wcmV2JGRhdGUgJT4lIHN1bW1hcnkoKQpkZl91a19zb2NkaXN0JGRhdGUgJT4lIHN1bW1hcnkoKQpgYGAKCiMjIyBDb250cm9sIGZvciB3ZWVrZW5kIGVmZmVjdCBpbiBzb2NpYWwgZGlzdGFuY2luZwpgYGB7cn0KCmRmX3VrX2xvZXNzIDwtIGRmX3VrX3NvY2Rpc3QgJT4lIAogIG11dGF0ZSh3ZWVrZGF5ID0gZm9ybWF0KGRhdGUsICcldScpKSAlPiUgCiAgZmlsdGVyKCF3ZWVrZGF5ICVpbiUgYygnNicsJzcnKSkgJT4lIAogIHNwbGl0KC4kbnV0czMpICU+JQogIG1hcCh+IGxvZXNzKHNvY2Rpc3Rfc2luZ2xlX3RpbGUgfiB0aW1lLCBkYXRhID0gLikpICU+JQogIG1hcChwcmVkaWN0LCAxOm1heChkZl91a19zb2NkaXN0JHRpbWUpKSAlPiUgCiAgYmluZF9yb3dzKCkgJT4lIAogIGdhdGhlcihrZXkgPSAnbnV0czMnLCB2YWx1ZSA9ICdsb2VzcycpICU+JSAKICBncm91cF9ieShudXRzMykgJT4lIAogIG11dGF0ZSh0aW1lID0gcm93X251bWJlcigpKQoKZGZfdWtfbG9lc3MKCmRmX3VrX3NvY2Rpc3QgPC0gZGZfdWtfc29jZGlzdCAlPiUgbWVyZ2UoZGZfdWtfbG9lc3MsIGJ5PWMoJ251dHMzJywgJ3RpbWUnKSkgJT4lIAogIG11dGF0ZSh3ZWVrZGF5ID0gZm9ybWF0KGRhdGUsICcldScpKSAlPiUgCiAgbXV0YXRlKHNvY2Rpc3Rfc2luZ2xlX3RpbGVfY2xlYW4gPSBpZmVsc2Uod2Vla2RheSAlaW4lIGMoJzYnLCc3JyksIGxvZXNzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvY2Rpc3Rfc2luZ2xlX3RpbGUpKSAlPiUKICBhcnJhbmdlKG51dHMzLCB0aW1lKSAlPiUgCiAgc2VsZWN0KC13ZWVrZGF5KQoKCmRmX3VrX3NvY2Rpc3QgPC0gZGZfdWtfc29jZGlzdCAlPiUgZHJvcF9uYSgpICU+JSBtdXRhdGUodGltZSA9IHRpbWUtMSkKCmBgYAoKIyBFeHBsb3JlIGRhdGEKCiMjIyBQbG90IHByZXZhbGVuY2Ugb3ZlciB0aW1lCmBgYHtyfQoKZGZfdWtfcHJldiAlPiUgZ2dwbG90KGFlcyh4PXRpbWUsIHk9cmF0ZV9kYXkpKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbD11dF9hcmVhLCBzaXplPXBvcGRlbnMpKSArIAogIGdlb21fc21vb3RoKG1ldGhvZD0ibG9lc3MiLCBzZT1UKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICBnZ3RpdGxlKCJPdmVyYWxsIHByZXZhbGVuY2Ugb3ZlciB0aW1lIikKCnBlcnMgPC0gYygncGVyc19vJywgJ3BlcnNfYycsICdwZXJzX2UnLCAncGVyc19hJywgJ3BlcnNfbicpCgpmb3IgKGkgaW4gcGVycyl7CgpnZyA8LSBkZl91a19wcmV2ICU+JSBtdXRhdGUocHJldl90YWlsID0gY3V0KC5bW2ldXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoLUluZiwgcXVhbnRpbGUoLltbaV1dLCAwLjIpLCBxdWFudGlsZSguW1tpXV0sIDAuOCksIEluZiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoJ2xvd2VyIHRhaWwnLCAnY2VudGVyJywgJ3VwcGVyIHRhaWwnKSkpICU+JSAKICBmaWx0ZXIocHJldl90YWlsICE9ICdjZW50ZXInKSAlPiUKICBnZ3Bsb3QoYWVzKHg9dGltZSwgeT1yYXRlX2RheSkpICsgCiAgZ2VvbV9wb2ludChhZXMoY29sPXV0X2FyZWEsIHNpemU9cG9wZGVucykpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsb2VzcyIsIHNlPVQpICsgCiAgZmFjZXRfd3JhcCh+cHJldl90YWlsKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICBnZ3RpdGxlKGkpCgpwcmludChnZykKfQoKYGBgCgojIyMgRXhwbG9yZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIGxvbmRvbiBhbmQgdGhlIHJlc3QgCmBgYHtyfQoKZGZfdWtfcHJldiAlPiUgZ2dwbG90KGFlcyh4PXRpbWUsIHk9cmF0ZV9kYXkpKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbD11dF9hcmVhLCBzaXplPXBvcGRlbnMpKSArIAogIGdlb21fc21vb3RoKG1ldGhvZD0ibG9lc3MiLCBzZT1UKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICBmYWNldF93cmFwKH5sb25kb24pICsKICBnZ3RpdGxlKCJPdmVyYWxsIHByZXZhbGVuY2Ugb3ZlciB0aW1lIikKCgoKYGBgCgojIyMgUGxvdCBzb2NpYWwgZGlzdGFuY2luZyBvdmVyIHRpbWUKYGBge3J9CgpkZl91a19zb2NkaXN0ICU+JSBnZ3Bsb3QoYWVzKHg9dGltZSwgeT1zb2NkaXN0X3NpbmdsZV90aWxlX2NsZWFuKSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2w9bnV0czMsIHNpemU9cG9wZGVucykpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsb2VzcyIsIHNlPVQpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKwogIGdndGl0bGUoIk92ZXJhbGwgc29jaWFsIGRpc3RhbmNpbmcgb3ZlciB0aW1lIikKCnBlcnMgPC0gYygncGVyc19vJywgJ3BlcnNfYycsICdwZXJzX2UnLCAncGVyc19hJywgJ3BlcnNfbicpCgpmb3IgKGkgaW4gcGVycyl7CgpnZyA8LSBkZl91a19zb2NkaXN0ICU+JSBtdXRhdGUoc29jZGlzdF90YWlsID0gY3V0KC5bW2ldXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoLUluZiwgcXVhbnRpbGUoLltbaV1dLCAwLjIpLCBxdWFudGlsZSguW1tpXV0sIDAuOCksIEluZiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoJ2xvd2VyIHRhaWwnLCAnY2VudGVyJywgJ3VwcGVyIHRhaWwnKSkpICU+JSAKICBmaWx0ZXIoc29jZGlzdF90YWlsICE9ICdjZW50ZXInKSAlPiUKICBnZ3Bsb3QoYWVzKHg9dGltZSwgeT1zb2NkaXN0X3NpbmdsZV90aWxlX2NsZWFuKSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2w9bnV0czMsIHNpemU9cG9wZGVucykpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsb2VzcyIsIHNlPVQpICsgCiAgZmFjZXRfd3JhcCh+c29jZGlzdF90YWlsKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICBnZ3RpdGxlKGkpCgpwcmludChnZykKfQoKYGBgCgoKYGBge3J9CmRmX3VrX3NvY2Rpc3QgJT4lIGdncGxvdChhZXMoeD10aW1lLCB5PXNvY2Rpc3Rfc2luZ2xlX3RpbGVfY2xlYW4pKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbD1udXRzMywgc2l6ZT1wb3BkZW5zKSkgKyAKICBnZW9tX3Ntb290aChtZXRob2Q9ImxvZXNzIiwgc2U9VCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSArCiAgZmFjZXRfd3JhcCh+bG9uZG9uKSArCiAgZ2d0aXRsZSgiT3ZlcmFsbCBzb2NpYWwgZGlzdGFuY2luZyBvdmVyIHRpbWUiKQpgYGAKCmBgYHtyfQoKZGZfdWtfc29jZGlzdCA8LSBkZl91a19zb2NkaXN0ICU+JSBtdXRhdGUoc29jZGlzdF9zaW5nbGVfdGlsZSA9IHNvY2Rpc3Rfc2luZ2xlX3RpbGVfY2xlYW4pICU+JSAKICBzZWxlY3QoLWxvZXNzLCAtc29jZGlzdF9zaW5nbGVfdGlsZV9jbGVhbikKCmBgYAoKIyMjIENvcnJlbGF0aW9ucwpgYGB7cn0KCmRmX3VrX3ByZXYgJT4lIGdyb3VwX2J5KHV0X2FyZWEpICU+JSAKICBzdW1tYXJpemVfaWYoaXMubnVtZXJpYywgbWVhbiwgbmEucm09VCkgJT4lIAogIHNlbGVjdCgtdXRfYXJlYSwgLXRpbWUpICU+JSAKICBjb3IodXNlID0gJ3BhaXJ3aXNlLmNvbXBsZXRlJykgJT4lIHJvdW5kKDMpICU+JQogIGFzLmRhdGEuZnJhbWUoKQoKZGZfdWtfc29jZGlzdCAlPiUgZ3JvdXBfYnkobnV0czMpICU+JSAKICBzdW1tYXJpemVfaWYoaXMubnVtZXJpYywgbWVhbiwgbmEucm09VCkgJT4lIAogIHNlbGVjdCgtbnV0czMsIC10aW1lKSAlPiUgCiAgY29yKHVzZSA9ICdwYWlyd2lzZS5jb21wbGV0ZScpICU+JSByb3VuZCgzKSAlPiUgCiAgYXMuZGF0YS5mcmFtZSgpCgpgYGAKCgojIyBSZXNjYWxlIERhdGEKYGBge3J9Cmx2bDJfc2NhbGVkX3V0IDwtIGRmX3VrX3ByZXYgJT4lIAogIGRwbHlyOjpzZWxlY3QoLXRpbWUsIC1kYXRlLCAtcmF0ZV9kYXksIC1sb25kb24pICU+JSAKICBkaXN0aW5jdCgpICU+JSAKICBtdXRhdGVfYXQodmFycygtdXRfYXJlYSksIHNjYWxlKQoKbHZsMV9zY2FsZWRfdXQgPC0gZGZfdWtfcHJldiAlPiUgc2VsZWN0KHV0X2FyZWEsIHRpbWUsIHJhdGVfZGF5KQoKZGZfdWtfcHJldl9zY2FsZWQgPC0gcGx5cjo6am9pbihsdmwxX3NjYWxlZF91dCwgbHZsMl9zY2FsZWRfdXQsIGJ5ID0gJ3V0X2FyZWEnKQoKZGZfdWtfcHJldl9zY2FsZWQKYGBgCgoKYGBge3J9CgpsdmwyX3NjYWxlZF9udXRzIDwtIGRmX3VrX3NvY2Rpc3QgJT4lIAogIGRwbHlyOjpzZWxlY3QoLXRpbWUsIC1kYXRlLCAtbG9uZG9uLCAKICAgICAgICAgICAgICAgIC1zb2NkaXN0X3RpbGVzLCAtc29jZGlzdF9zaW5nbGVfdGlsZSwgLXJhdGVfZGF5KSAlPiUgCiAgZGlzdGluY3QoKSAlPiUgCiAgbXV0YXRlX2F0KHZhcnMoLW51dHMzKSwgc2NhbGUpCgpsdmwxX3NjYWxlZF9udXRzIDwtIGRmX3VrX3NvY2Rpc3QgJT4lIHNlbGVjdChudXRzMywgdGltZSwgc29jZGlzdF9zaW5nbGVfdGlsZSwgcmF0ZV9kYXkpICU+JSAKICBtdXRhdGVfYXQodmFycygtbnV0czMsIC10aW1lLCAtIHJhdGVfZGF5KSwgc2NhbGUpCgpkZl91a19zb2NkaXN0X3NjYWxlZCA8LSBwbHlyOjpqb2luKGx2bDFfc2NhbGVkX251dHMsIGx2bDJfc2NhbGVkX251dHMsIGJ5ID0gJ251dHMzJykKCmRmX3VrX3NvY2Rpc3Rfc2NhbGVkCgpgYGAKCgoKCiMgUHJlZGljdCBQcmV2YWxlbmNlCiMjIyBFeHRyYWN0IGZpcnN0IGRheSBvZiBjb3ZpZCBvdXRicmVhawpgYGB7cn0KCiMgZ2V0IG9uc2V0IGRheQpkZl91a19vbnNldF9wcmV2IDwtIGRmX3VrX3ByZXZfc2NhbGVkICU+JSAKICBncm91cF9ieSh1dF9hcmVhKSAlPiUgCiAgbXV0YXRlKHJhdGVfY3MgPSBjdW1zdW0ocmF0ZV9kYXkpKSAlPiUgCiAgZmlsdGVyKHJhdGVfY3MgPiAwKSAlPiUKICBzdW1tYXJpemUob25zZXRfcHJldiA9IG1pbih0aW1lKSkKICAKIyBtZXJnZSB3aXRoIGNvdW50eSBkYXRhCmRmX3VrX29uc2V0X3ByZXYgPC0gZGZfdWtfcHJldl9zY2FsZWQgJT4lIAogIHNlbGVjdCgtdGltZSwgLXJhdGVfZGF5KSAlPiUKICBkaXN0aW5jdCgpICU+JSAKICBsZWZ0X2pvaW4oZGZfdWtfb25zZXRfcHJldiwgYnkgPSAndXRfYXJlYScpCgojIGhhbmRsZSBjZW5zb3JlZCBkYXRhCmRmX3VrX29uc2V0X3ByZXYgPC0gZGZfdWtfb25zZXRfcHJldiAlPiUgCiAgbXV0YXRlKGV2ZW50ID0gaWZlbHNlKGlzLm5hKG9uc2V0X3ByZXYpLCAwLCAxKSkgJT4lIAogIG11dGF0ZShvbnNldF9wcmV2ID0gcmVwbGFjZV9uYShvbnNldF9wcmV2LCBhcy5udW1lcmljKGRpZmYocmFuZ2UoZGZfdWtfcHJldiRkYXRlKSkpKzEpKQoKZGZfdWtfb25zZXRfcHJldgoKYGBgCgojIyMgRXh0cmFjdCBzbG9wZXMKYGBge3J9CgojIGN1dCB0aW1lIHNlcmllcyBiZWZvcmUgb25zZXQKZGZfdWtfcHJldl9zY2FsZWQgPC0gZGZfdWtfcHJldl9zY2FsZWQgJT4lIAogIGdyb3VwX2J5KHV0X2FyZWEpICU+JSAKICBtdXRhdGUocmF0ZV9jcyA9IGN1bXN1bShyYXRlX2RheSkpICU+JSAKICBmaWx0ZXIocmF0ZV9jcyA+IDApICU+JQogIG11dGF0ZSh0aW1lID0gdGltZS1taW4odGltZSkrMSkgJT4lCiAgdW5ncm91cCgpICU+JQogIGZpbHRlcih0aW1lIDw9IDMwKSAlPiUKICBzZWxlY3QoLXJhdGVfY3MpCgojIGRyb3AgY291bnRpZXMgd2l0aCBsaXR0bGUgZGF0YQpkZl91a19wcmV2X3NjYWxlZCA8LSBkZl91a19wcmV2X3NjYWxlZCAlPiUKICBncm91cF9ieSh1dF9hcmVhKSAlPiUKICBmaWx0ZXIobigpID09IDMwKSAlPiUKICB1bmdyb3VwKCkKCiMgZXh0cmFjdCBzbG9wZSBwcmV2YWxlbmNlCmRmX3VrX3Nsb3BlX3ByZXYgPC0gZGZfdWtfcHJldl9zY2FsZWQgJT4lIHNwbGl0KC4kdXRfYXJlYSkgJT4lIAogIG1hcCh+IGxtKHJhdGVfZGF5IH4gdGltZSwgZGF0YSA9IC4pKSAlPiUKICBtYXAoY29lZikgJT4lIAogIG1hcF9kYmwoJ3RpbWUnKSAlPiUgCiAgYXMuZGF0YS5mcmFtZSgpICU+JSAKICByb3duYW1lc190b19jb2x1bW4oJ3V0X2FyZWEnKSAlPiUgCiAgcmVuYW1lKHNsb3BlX3ByZXYgPSAnLicpCgojIG1lcmdlIHdpdGggY291bnR5IGRhdGEKZGZfdWtfc2xvcGVfcHJldiA8LSBkZl91a19wcmV2X3NjYWxlZCAlPiUgCiAgc2VsZWN0KC10aW1lLCAtcmF0ZV9kYXkpICU+JQogIGRpc3RpbmN0KCkgJT4lIAogIGlubmVyX2pvaW4oZGZfdWtfc2xvcGVfcHJldiwgYnkgPSAndXRfYXJlYScpICU+JQogIGRyb3BfbmEoKQoKYGBgCgoKIyMjIEV4cGxvcmUgZGlzdHJpYnV0aW9ucwpgYGB7cn0KCmRmX3VrX29uc2V0X3ByZXYgJT4lIGdncGxvdChhZXMob25zZXRfcHJldikpICsgZ2VvbV9oaXN0b2dyYW0oKQpkZl91a19zbG9wZV9wcmV2ICU+JSBnZ3Bsb3QoYWVzKHNsb3BlX3ByZXYpKSArIGdlb21faGlzdG9ncmFtKCkKCmBgYAoKCiMjIFByZWRpY3QgQ09WSUQgb25zZXQgd2l0aCB0aW1lLXRvLWV2ZW50IHJlZ3Jlc3Npb24gCmBgYHtyfQoKIyBwcmVkaWN0IG9uc2V0IGZyb20gcGVyc29uYWxpdHkKY294X29uc2V0X3ByZXYgPC0gY294cGgoU3VydihvbnNldF9wcmV2LCBldmVudCkgfiAKICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJzX28gKyBwZXJzX2MgKyBwZXJzX2UgKyBwZXJzX2EgKyBwZXJzX24sIAogICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGZfdWtfb25zZXRfcHJldikKY294X29uc2V0X3ByZXYgJT4lIHN1bW1hcnkoKQoKIyBwcmVkaWN0IG9uc2V0IGZyb20gcGVyc29uYWxpdHkgd2l0aCBjb250cm9scwpjb3hfb25zZXRfcHJldl9jdHJsIDwtIGNveHBoKFN1cnYob25zZXRfcHJldiwgZXZlbnQpIH4gCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJzX28gKyBwZXJzX2MgKyBwZXJzX2UgKyBwZXJzX2EgKyBwZXJzX24gKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWlycG9ydF9kaXN0ICsgbWFsZXMgKyBwb3BkZW5zICsgbWFudWZhY3R1cmluZyArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG91cmlzbSArIGhlYWx0aCArIGFjYWRlbWljICsgbWVkaW5jICsgbWVkYWdlICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNlcnZhdGl2ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGZfdWtfb25zZXRfcHJldikKY294X29uc2V0X3ByZXZfY3RybCAlPiUgc3VtbWFyeSgpCgpgYGAKCiMjIFByZWRpY3QgcHJldmFsZW5jZSBzbG9wZXMgd2l0aCBsaW5lYXIgbW9kZWxzCmBgYHtyfQoKIyBwcmVkaWN0IHNsb3BlcyBmcm9tIHBlcnNvbmFsaXR5CmxtX3Nsb3BlX3ByZXYgPC0gbG0oc2xvcGVfcHJldiB+IHBlcnNfbyArIHBlcnNfYyArIHBlcnNfZSArIHBlcnNfYSArIHBlcnNfbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGZfdWtfc2xvcGVfcHJldikKbG1fc2xvcGVfcHJldiAlPiUgc3VtbWFyeSgpCgojIHByZWRpY3Qgc2xvcGVzIGZyb20gcGVyc29uYWxpdHkgd2l0aCBjb250cm9scwpsbV9zbG9wZV9wcmV2X2N0cmwgPC0gbG0oc2xvcGVfcHJldiB+ICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlcnNfbyArIHBlcnNfYyArIHBlcnNfZSArIHBlcnNfYSArIHBlcnNfbiArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhaXJwb3J0X2Rpc3QgKyBtYWxlcyArIHBvcGRlbnMgKyBtYW51ZmFjdHVyaW5nICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3VyaXNtICsgaGVhbHRoICsgYWNhZGVtaWMgKyBtZWRpbmMgKyBtZWRhZ2UgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc2VydmF0aXZlLAogICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRmX3VrX3Nsb3BlX3ByZXYpCmxtX3Nsb3BlX3ByZXZfY3RybCAlPiUgc3VtbWFyeSgpCgpgYGAKCiMjIyBDUkYgcHJlZGljdGluZyBzbG9wZXMKYGBge3J9CgpjdHJscyA8LSBjZm9yZXN0X3VuYmlhc2VkKG50cmVlPTUwMCwgbXRyeT01KQoKY3JmX3Nsb3BlX3ByZXYgPC0gY2ZvcmVzdChzbG9wZV9wcmV2IH4gIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVyc19vICsgcGVyc19jICsgcGVyc19lICsgcGVyc19hICsgcGVyc19uICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFpcnBvcnRfZGlzdCArIG1hbGVzICsgcG9wZGVucyArIG1hbnVmYWN0dXJpbmcgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdXJpc20gKyBoZWFsdGggKyBhY2FkZW1pYyArIG1lZGluYyArIG1lZGFnZSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zZXJ2YXRpdmUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl91a19zbG9wZV9wcmV2LCAKICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2xzID0gY3RybHMpCgpjcmZfc2xvcGVfcHJldl92YXJpbXAgPC0gdmFyaW1wKGNyZl9zbG9wZV9wcmV2LCBucGVybSA9IDEpCmNyZl9zbG9wZV9wcmV2X3ZhcmltcF9jb25kIDwtIHZhcmltcChjcmZfc2xvcGVfcHJldiwgY29uZGl0aW9uYWwgPSBULCBucGVybSA9IDEpCgpjcmZfc2xvcGVfcHJldl92YXJpbXAgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgcm93bmFtZXNfdG9fY29sdW1uKCd2YXJpYWJsZScpICU+JQogIGdncGxvdChhZXMoeD12YXJpYWJsZSwgeT0uKSkgKwogIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKQoKY3JmX3Nsb3BlX3ByZXZfdmFyaW1wX2NvbmQgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgcm93bmFtZXNfdG9fY29sdW1uKCd2YXJpYWJsZScpICU+JQogIGdncGxvdChhZXMoeD12YXJpYWJsZSwgeT0uKSkgKwogIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpCgpgYGAKCiMjIFByZWRpY3QgU29jaWFsIERpc3RhbmNpbmcKIyMjIENoYW5nZSBwb2ludCBhbmFseXNpcwpgYGB7cn0KCiMga2VlcCBvbmx5IGNvdW50aWVzIHdpdGggZnVsbCBkYXRhCm51dHNfY29tcGxldGUgPC0gZGZfdWtfc29jZGlzdF9zY2FsZWQgJT4lIAogIGdyb3VwX2J5KG51dHMzKSAlPiUgCiAgc3VtbWFyaXplKG4gPSBuKCkpICU+JSAKICBmaWx0ZXIobj09bWF4KC4kbikpICU+JSAKICAuJG51dHMzCgojIHJ1biBjaGFuZ2Vwb2ludCBhbmFseXNpcwpkZl91a19zb2NkaXN0X2NwdF9yZXN1bHRzIDwtIGRmX3VrX3NvY2Rpc3Rfc2NhbGVkICU+JSAKICBzZWxlY3QobnV0czMsIHNvY2Rpc3Rfc2luZ2xlX3RpbGUpICU+JQogIGZpbHRlcihudXRzMyAlaW4lIG51dHNfY29tcGxldGUpICU+JSAKICBzcGxpdCguJG51dHMzKSAlPiUKICBtYXAofiBjcHQubWVhbnZhcihhcy52ZWN0b3IoLiRzb2NkaXN0X3NpbmdsZV90aWxlKSwKICAgICAgICAgICAgICAgICAgICAjcGVuYWx0eSA9ICdBc3ltcHRvdGljJywKICAgICAgICAgICAgICAgICAgICBjbGFzcz1UUlVFLAogICAgICAgICAgICAgICAgICAgIHBhcmFtLmVzdGltYXRlcz1UUlVFLAogICAgICAgICAgICAgICAgICAgIFE9MSwKICAgICAgICAgICAgICAgICAgICB0ZXN0LnN0YXQgPSAnTm9ybWFsJykpCgojIGNhbGN1bGF0ZSBjaGFuZ2UgcG9pbnQKZGZfdWtfc29jZGlzdF9jcHRfZGF5IDwtIGRmX3VrX3NvY2Rpc3RfY3B0X3Jlc3VsdHMgJT4lIAogIG1hcChjcHRzKSAlPiUgCiAgdW5saXN0KCkgJT4lIAogIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgcmVuYW1lKGNwdF9kYXlfc29jZGlzdCA9ICcuJykgJT4lCiAgcm93bmFtZXNfdG9fY29sdW1uKCdudXRzMycpCgojIGNhbGN1bGF0ZSBtZWFuIGRpZmZlcmVuY2VzCmRmX3VrX3NvY2Rpc3RfY3B0X21lYW5fZGlmZiA8LSBkZl91a19zb2NkaXN0X2NwdF9yZXN1bHRzICU+JSAKICBtYXAocGFyYW0uZXN0KSAlPiUgCiAgbWFwKH4gLiRtZWFuKSAlPiUgCiAgbWFwKH4gLlsyXS0uWzFdKSAlPiUgCiAgdW5saXN0KCkgJT4lIAogIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgcmVuYW1lKG1lYW5fZGlmZl9zb2NkaXN0ID0gJy4nKSAlPiUKICByb3duYW1lc190b19jb2x1bW4oJ251dHMzJykKCiMgY2FsY3VsYXRlIHZhcmFpbmNlIGRpZmZlcmVuY2VzCmRmX3VrX3NvY2Rpc3RfY3B0X3Zhcl9kaWZmIDwtIGRmX3VrX3NvY2Rpc3RfY3B0X3Jlc3VsdHMgJT4lIAogIG1hcChwYXJhbS5lc3QpICU+JSAKICBtYXAofiAuJHZhcmlhbmNlKSAlPiUgCiAgbWFwKH4gLlsyXS0uWzFdKSAlPiUgCiAgdW5saXN0KCkgJT4lIAogIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgcmVuYW1lKHZhcl9kaWZmX3NvY2Rpc3QgPSAnLicpICU+JQogIHJvd25hbWVzX3RvX2NvbHVtbignbnV0czMnKQoKIyBtZXJnZSB3aXRoIGNvdW50eSBkYXRhCmRmX3VrX2NwdF9zb2NkaXN0IDwtIGRmX3VrX3NvY2Rpc3Rfc2NhbGVkICU+JSAKICBzZWxlY3QoLXRpbWUsIC1yYXRlX2RheSwgLXNvY2Rpc3Rfc2luZ2xlX3RpbGUpICU+JQogIGRpc3RpbmN0KCkgJT4lIAogIGxlZnRfam9pbihkZl91a19zb2NkaXN0X2NwdF9kYXksIGJ5PSdudXRzMycpICU+JQogIGxlZnRfam9pbihkZl91a19zb2NkaXN0X2NwdF9tZWFuX2RpZmYsIGJ5PSdudXRzMycpICU+JQogIGxlZnRfam9pbihkZl91a19zb2NkaXN0X2NwdF92YXJfZGlmZiwgYnk9J251dHMzJykgJT4lCiAgbGVmdF9qb2luKG51dHNfdXRfa2V5LCBieT0nbnV0czMnKSAlPiUgCiAgbGVmdF9qb2luKHNlbGVjdChkZl91a19vbnNldF9wcmV2LCB1dF9hcmVhLCBvbnNldF9wcmV2KSwgYnk9J3V0X2FyZWEnKSAlPiUKICBsZWZ0X2pvaW4oc2VsZWN0KGRmX3VrX3Nsb3BlX3ByZXYsIHV0X2FyZWEsIHNsb3BlX3ByZXYpLCBieT0ndXRfYXJlYScpICU+JQogIHNlbGVjdCgtdXRfYXJlYSkKCiMgaGFuZGxlIGNlbnNvcmVkIGRhdGEKZGZfdWtfY3B0X3NvY2Rpc3QgPC0gZGZfdWtfY3B0X3NvY2Rpc3QgJT4lIAogIG11dGF0ZShjcHRfZGF5X3NvY2Rpc3QgPSBpZmVsc2UoaXMubmEoY3B0X2RheV9zb2NkaXN0KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcy5udW1lcmljKGRpZmYocmFuZ2UoZGZfdXMkZGF0ZSkpKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcHRfZGF5X3NvY2Rpc3QpKSAlPiUgCiAgbXV0YXRlKGV2ZW50ID0gaWZlbHNlKGNwdF9kYXlfc29jZGlzdCA+PSA2MCwgMCwgMSkpCgpgYGAKCmBgYHtyfQpkZl91a19jcHRfc29jZGlzdCRjcHRfZGF5X3NvY2Rpc3QgJT4lIGhpc3QoKQpkZl91a19jcHRfc29jZGlzdCRtZWFuX2RpZmZfc29jZGlzdCAlPiUgaGlzdCgpCmRmX3VrX2NwdF9zb2NkaXN0JHZhcl9kaWZmX3NvY2Rpc3QgJT4lIGhpc3QoKQoKYGBgCgpgYGB7cn0KCmZvcihpIGluIGhlYWQoZGZfdWtfc29jZGlzdF9jcHRfcmVzdWx0cywgNSkpewogIHBsb3QoaSkKfQoKYGBgCgoKIyBQcmVkaWN0aW5nIGNoYW5nZSBwb2ludHMgd2l0aCB0aW1lLXRvLWV2ZW50IHJlZ3Jlc3Npb24gCmBgYHtyfQoKIyBwcmVkaWN0IGhhemFyZCBmcm9tIHBlcnNvbmFsaXR5CmNveF9jcHRfc29jZGlzdCA8LSBjb3hwaChTdXJ2KGNwdF9kYXlfc29jZGlzdCwgZXZlbnQpIH4gCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlcnNfbyArIHBlcnNfYyArIHBlcnNfZSArIHBlcnNfYSArIHBlcnNfbiwgCiAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl91a19jcHRfc29jZGlzdCkKY294X2NwdF9zb2NkaXN0ICU+JSBzdW1tYXJ5KCkKCiMgcHJlZGljdCBoYXphcmQgZnJvbSBwZXJzb25hbGl0eSB3aXRoIGNvbnRyb2xzCmNveF9jcHRfc29jZGlzdF9jdHJsIDwtIGNveHBoKFN1cnYoY3B0X2RheV9zb2NkaXN0LCBldmVudCkgfiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJzX28gKyBwZXJzX2MgKyBwZXJzX2UgKyBwZXJzX2EgKyBwZXJzX24gKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWlycG9ydF9kaXN0ICsgbWFsZXMgKyBwb3BkZW5zICsgbWFudWZhY3R1cmluZyArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG91cmlzbSArIGhlYWx0aCArIGFjYWRlbWljICsgbWVkaW5jICsgbWVkYWdlICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNlcnZhdGl2ZSwKICAgICAgICAgICAgICAgICAgZGF0YSA9IGRmX3VrX2NwdF9zb2NkaXN0KQpjb3hfY3B0X3NvY2Rpc3RfY3RybCAlPiUgc3VtbWFyeSgpCgojIHByZWRpY3QgaGF6YXJkIGZyb20gcGVyc29uYWxpdHkgd2l0aCBjb250cm9scwpjb3hfY3B0X3NvY2Rpc3RfY3RybDIgPC0gY294cGgoU3VydihjcHRfZGF5X3NvY2Rpc3QsIGV2ZW50KSB+IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJzX28gKyBwZXJzX2MgKyBwZXJzX2UgKyBwZXJzX2EgKyBwZXJzX24gKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWlycG9ydF9kaXN0ICsgbWFsZXMgKyBwb3BkZW5zICsgbWFudWZhY3R1cmluZyArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG91cmlzbSArIGhlYWx0aCArIGFjYWRlbWljICsgbWVkaW5jICsgbWVkYWdlICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNlcnZhdGl2ZSArIG9uc2V0X3ByZXYgKyBzbG9wZV9wcmV2LAogICAgICAgICAgICAgICAgICBkYXRhID0gZGZfdWtfY3B0X3NvY2Rpc3QpCmNveF9jcHRfc29jZGlzdF9jdHJsMiAlPiUgc3VtbWFyeSgpCgpgYGAKCiMjIyBMaW5lYXIgbW9kZWxzIHByZWRpY3RpbmcgbWVhbiBkaWZmZXJlbmNlcwpgYGB7cn0KCmxtX21lYW5kaWZmX3NvY2Rpc3QgPC0gbG0obWVhbl9kaWZmX3NvY2Rpc3QgfiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlcnNfbyArIHBlcnNfYyArIHBlcnNfZSArIHBlcnNfYSArIHBlcnNfbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGZfdWtfY3B0X3NvY2Rpc3QpCmxtX21lYW5kaWZmX3NvY2Rpc3QgJT4lIHN1bW1hcnkoKQoKbG1fbWVhbmRpZmZfc29jZGlzdF9jdHJsIDwtIGxtKG1lYW5fZGlmZl9zb2NkaXN0IH4gCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlcnNfbyArIHBlcnNfYyArIHBlcnNfZSArIHBlcnNfYSArIHBlcnNfbiArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhaXJwb3J0X2Rpc3QgKyBtYWxlcyArIHBvcGRlbnMgKyBtYW51ZmFjdHVyaW5nICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3VyaXNtICsgaGVhbHRoICsgYWNhZGVtaWMgKyBtZWRpbmMgKyBtZWRhZ2UgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc2VydmF0aXZlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRmX3VrX2NwdF9zb2NkaXN0KQpsbV9tZWFuZGlmZl9zb2NkaXN0X2N0cmwgJT4lIHN1bW1hcnkoKQoKbG1fbWVhbmRpZmZfc29jZGlzdF9jdHJsMiA8LSBsbShtZWFuX2RpZmZfc29jZGlzdCB+IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVyc19vICsgcGVyc19jICsgcGVyc19lICsgcGVyc19hICsgcGVyc19uICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFpcnBvcnRfZGlzdCArIG1hbGVzICsgcG9wZGVucyArIG1hbnVmYWN0dXJpbmcgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdXJpc20gKyBoZWFsdGggKyBhY2FkZW1pYyArIG1lZGluYyArIG1lZGFnZSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zZXJ2YXRpdmUgKyBvbnNldF9wcmV2ICsgc2xvcGVfcHJldiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl91a19jcHRfc29jZGlzdCkKbG1fbWVhbmRpZmZfc29jZGlzdF9jdHJsMiAlPiUgc3VtbWFyeSgpCgpgYGAKCiMjIyBDUkYgcHJlZGljdGluZyBtZWFuIGRpZmZlcmVuY2UKYGBge3J9CgpjdHJscyA8LSBjZm9yZXN0X3VuYmlhc2VkKG50cmVlPTUwMCwgbXRyeT01KQoKY3JmX21lYW5kaWZmX3NvY2Rpc3QgPC0gY2ZvcmVzdChtZWFuX2RpZmZfc29jZGlzdCB+IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVyc19vICsgcGVyc19jICsgcGVyc19lICsgcGVyc19hICsgcGVyc19uICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFpcnBvcnRfZGlzdCArIG1hbGVzICsgcG9wZGVucyArIG1hbnVmYWN0dXJpbmcgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdXJpc20gKyBoZWFsdGggKyBhY2FkZW1pYyArIG1lZGluYyArIG1lZGFnZSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zZXJ2YXRpdmUgKyBvbnNldF9wcmV2ICsgc2xvcGVfcHJldiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl91a19jcHRfc29jZGlzdCAlPiUgZHJvcF9uYSgpLAogICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbHMgPSBjdHJscykKCmNyZl9tZWFuZGlmZl9zb2NkaXN0X3ZhcmltcCA8LSB2YXJpbXAoY3JmX21lYW5kaWZmX3NvY2Rpc3QsIG5wZXJtID0gMSkKY3JmX21lYW5kaWZmX3NvY2Rpc3RfdmFyaW1wX2NvbmQgPC0gdmFyaW1wKGNyZl9tZWFuZGlmZl9zb2NkaXN0LCBjb25kaXRpb25hbCA9IFQsIG5wZXJtID0gMSkKCmNyZl9tZWFuZGlmZl9zb2NkaXN0X3ZhcmltcCAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSAKICByb3duYW1lc190b19jb2x1bW4oJ3ZhcmlhYmxlJykgJT4lCiAgZ2dwbG90KGFlcyh4PXZhcmlhYmxlLCB5PS4pKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKCmNyZl9tZWFuZGlmZl9zb2NkaXN0X3ZhcmltcF9jb25kICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIAogIHJvd25hbWVzX3RvX2NvbHVtbigndmFyaWFibGUnKSAlPiUKICBnZ3Bsb3QoYWVzKHg9dmFyaWFibGUsIHk9LikpICsKICBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JykgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKQoKYGBg
Social distancing